package org.ehe.finance.voucher.service;

import com.baomidou.mybatisplus.extension.service.IService;
import org.ehe.finance.voucher.domain.ErpFinanceVoucherDetail;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.ehe.common.core.exception.ServiceException;
import org.ehe.common.mybatis.core.page.PageQuery;
import org.ehe.common.mybatis.core.page.TableDataInfo;
import org.ehe.common.satoken.utils.LoginHelper;
import org.ehe.finance.voucher.domain.ErpFinanceVoucher;
import org.ehe.finance.voucher.domain.ErpFinanceVoucherDetail;
import org.ehe.finance.voucher.domain.bo.*;
import org.ehe.finance.voucher.domain.vo.ErpFinanceVoucherDetailVo;
import org.ehe.finance.voucher.mapper.ErpFinanceVoucherDetailMapper;
import org.ehe.finance.voucher.mapper.ErpFinanceVoucherDetailMapper.VoucherDetailSummary;
import org.ehe.finance.voucher.mapper.ErpFinanceVoucherDetailMapper.VoucherTotalAmount;
import org.ehe.finance.voucher.service.ErpFinanceVoucherService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 记账凭证明细服务接口
 * @author :zhangnn
 * @className :ErpFinanceVoucherDetailService
 * @description: TODO
 * @date 2025-08-25 13:26:51
 */

public interface ErpFinanceVoucherDetailService extends IService<ErpFinanceVoucherDetail> {
    /**
     * 分页查询凭证明细
     * @param bo 查询条件
     * @param pageQuery 分页参数
     * @return 分页结果
     */
    TableDataInfo<ErpFinanceVoucherDetailVo> pageVoucherDetails(VoucherDetailQueryBo bo, PageQuery pageQuery);

    /**
     * 创建凭证明细
     * @param createBo 创建对象
     * @return 明细ID
     */
    Long createVoucherDetail(VoucherDetailCreateBo createBo);

    /**
     * 更新凭证明细
     * @param updateBo 更新对象
     */
    void updateVoucherDetail(VoucherDetailUpdateBo updateBo);

    /**
     * 删除凭证明细
     * @param id 明细ID
     */
    void deleteVoucherDetail(Long id);

    /**
     * 批量删除凭证明细
     * @param ids 明细ID列表
     */
    void batchDeleteVoucherDetails(List<Long> ids);

    /**
     * 根据ID获取明细详情
     * @param id 明细ID
     * @return 明细详情
     */
    ErpFinanceVoucherDetailVo getVoucherDetailById(Long id);

    /**
     * 根据凭证ID获取明细列表
     * @param voucherId 凭证ID
     * @return 明细列表
     */
    List<ErpFinanceVoucherDetailVo> getDetailsByVoucherId(Long voucherId);

    /**
     * 根据凭证ID批量获取明细列表
     * @param voucherIds 凭证ID列表
     * @return 明细列表
     */
    List<ErpFinanceVoucherDetailVo> getDetailsByVoucherIds(List<Long> voucherIds);

    /**
     * 批量保存凭证明细
     * @param batchSaveBo 批量保存对象
     */
    void batchSaveVoucherDetails(VoucherDetailBatchSaveBo batchSaveBo);

    /**
     * 删除凭证的所有明细
     * @param voucherId 凭证ID
     */
    void deleteDetailsByVoucherId(Long voucherId);

    /**
     * 获取凭证借贷合计
     * @param voucherId 凭证ID
     * @return 合计金额
     */
    VoucherTotalAmount getVoucherTotalAmount(Long voucherId);

    /**
     * 验证凭证明细是否平衡
     * @param voucherId 凭证ID
     * @return 是否平衡
     */
    boolean validateVoucherBalance(Long voucherId);

    /**
     * 获取下一个分录号
     * @param voucherId 凭证ID
     * @return 下一个分录号
     */
    Integer getNextEntryNo(Long voucherId);

    /**
     * 根据科目查询明细
     * @param subjectId 科目ID
     * @param startDate 开始日期
     * @param endDate 结束日期
     * @return 明细列表
     */
    List<ErpFinanceVoucherDetailVo> getDetailsBySubject(Long subjectId, LocalDate startDate, LocalDate endDate);

    /**
     * 根据辅助核算查询明细
     * @param customerId 客户ID
     * @param supplierId 供应商ID
     * @param employeeId 员工ID
     * @param projectId 项目ID
     * @param departmentId 部门ID
     * @param startDate 开始日期
     * @param endDate 结束日期
     * @return 明细列表
     */
    List<ErpFinanceVoucherDetailVo> getDetailsByAuxiliary(Long customerId, Long supplierId,
                                                          Long employeeId, Long projectId,
                                                          Long departmentId, LocalDate startDate,
                                                          LocalDate endDate);

    /**
     * 统计科目发生额
     * @param subjectIds 科目ID列表
     * @param startDate 开始日期
     * @param endDate 结束日期
     * @return 统计结果
     */
    List<VoucherDetailStatBo> getSubjectAmountStat(List<Long> subjectIds, LocalDate startDate, LocalDate endDate);

    /**
     * 获取凭证明细汇总
     * @param voucherId 凭证ID
     * @return 汇总数据
     */
    List<VoucherDetailSummary> getVoucherDetailSummary(Long voucherId);

    /**
     * 获取科目余额
     * @param subjectId 科目ID
     * @param endDate 截止日期
     * @return 余额
     */
    BigDecimal getSubjectBalance(Long subjectId, LocalDate endDate);

    /**
     * 复制凭证明细到新凭证
     * @param sourceVoucherId 源凭证ID
     * @param targetVoucherId 目标凭证ID
     */
    void copyVoucherDetails(Long sourceVoucherId, Long targetVoucherId);

    /**
     * 重新排序分录号
     * @param voucherId 凭证ID
     */
    void reorderEntryNos(Long voucherId);

    /**
     * 查询多币种明细
     * @param voucherId 凭证ID
     * @return 多币种明细
     */
    List<ErpFinanceVoucherDetailVo> getMultiCurrencyDetails(Long voucherId);

    /**
     * 验证明细数据
     * @param details 明细列表
     * @return 验证结果
     */
    ValidateResult validateDetails(List<VoucherDetailCreateBo> details);

    /**
     * 计算外币金额
     * @param amount 本币金额
     * @param exchangeRate 汇率
     * @return 外币金额
     */
    BigDecimal calculateForeignAmount(BigDecimal amount, BigDecimal exchangeRate);

    /**
     * 自动生成对方科目明细
     * @param voucherId 凭证ID
     * @param mainDetail 主要明细
     * @return 生成的明细列表
     */
    List<ErpFinanceVoucherDetail> generateCounterDetails(Long voucherId, VoucherDetailCreateBo mainDetail);

    /**
     * 导出凭证明细
     * @param bo 查询条件
     * @return 导出数据
     */
    List<ErpFinanceVoucherDetailVo> exportVoucherDetails(VoucherDetailQueryBo bo);

    /**
     * 验证结果内部类
     */
    class ValidateResult {
        private boolean valid;
        private String message;
        private List<String> errors;

        public ValidateResult() {}

        public ValidateResult(boolean valid, String message) {
            this.valid = valid;
            this.message = message;
        }

        // getters and setters
        public boolean isValid() { return valid; }
        public void setValid(boolean valid) { this.valid = valid; }
        public String getMessage() { return message; }
        public void setMessage(String message) { this.message = message; }
        public List<String> getErrors() { return errors; }
        public void setErrors(List<String> errors) { this.errors = errors; }
    }
}
